package dao;

import util.JdbcUtils;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 所有数据库操作类的公共父类
 *      1. 执行非DQL语句的方法  executeUpdate()
 *      2. 执行DQL语句的方法   executeQuery()
 */
public class BaseDao {
    /**
     * 执行非DQL语句的方法
     */
    public int executeUpdate(String sql, Object... params) throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //占位符赋值
        for (int i = 0; i < params.length; i++) {
            preparedStatement.setObject(i+1, params[i]);
        }
        int i = preparedStatement.executeUpdate();
        if (connection.getAutoCommit()) {
            JdbcUtils.freeConnection();
        }
        return i;
    }

    /**
     * 执行DQL语句的方法
     */
    public <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //占位符赋值
        for (int i = 0; i < params.length; i++) {
            preparedStatement.setObject(i+1, params[i]);
        }
        ResultSet resultSet = preparedStatement.executeQuery();
        //解析结果集：
        List<T> list = new ArrayList<>();   //最终所有数据集合，里面每个对象就是对应的实体类对象，如：User
        ResultSetMetaData metaData = resultSet.getMetaData();   //列信息对象
        int columnCount = metaData.getColumnCount();            //总列数
        while (resultSet.next()) {  //每一行数据
            T t = clazz.newInstance();  //调用实体类无参构造方法实例化对象  User user = new User();
            for (int i = 1; i <= columnCount; i++) {    //遍历列
                String columnLabel = metaData.getColumnLabel(i);    //列名
                Object value = resultSet.getObject(i);             //值
                //反射，给对象的属性赋值
                Field field = clazz.getDeclaredField(columnLabel);  //根据列名获取字段
                field.setAccessible(true);      //突破private的限制
                //给这个字段赋值   field.set(实体类对象, 要赋的值);
                field.set(t, value);
            }
            list.add(t);
        }

        return list;
    }
}
